/*
 * Copyright 2012 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package be.free.ts.support;

import org.springframework.data.domain.*;
import org.springframework.data.jpa.repository.JpaRepository;

import java.io.Serializable;
import java.util.List;

import static com.google.common.base.Preconditions.*;
import static com.google.common.collect.Lists.newArrayList;

/**
 * Simple Paging and Sorting service for Entities. The purpose is to offer a default facade for the GWT request factory.
 * When extending this class you need to override all methods you want to expose with the GWT request factory, otherwise
 * the request factory engine can't bind to the generic methods.
 *
 * @author Christophe De Blende
 * @since 05/01/13
 */
public abstract class PagingAndSortingService<R extends JpaRepository<T, K>, T extends Persistable<K>, K extends Serializable> {

	private final R repository;

	protected PagingAndSortingService(R jpaRepository) {
		this.repository = jpaRepository;
	}

	public T save(T entity) {
		return repository.save(entity);
	}

	public T findOne(K id) {
		checkArgument(id != null);
		return repository.findOne(id);
	}

	public Boolean exists(K id) {
		checkArgument(id != null);
		return repository.exists(id);
	}

	public List<T> save(List<T> entities) {
		return repository.save(entities);
	}

	public Long count() {
		return repository.count();
	}

	public void delete(K id) {
		checkState(!exists(id));
		repository.delete(id);
	}

	public void delete(T entity) {
		checkNotNull(entity);
		checkState(exists(entity.getId()));
		repository.delete(entity);
	}

	public void delete(List<T> entities) {
		checkArgument(entities != null);
		repository.delete(entities);
	}

	public void deleteAll() {
		repository.deleteAll();
	}

	public List<T> findAll() {
		return repository.findAll();
	}

	public List<T> findAll(List<K> ids) {
		return newArrayList(repository.findAll(ids));
	}

	public List<T> findAll(Sort sort) {
		checkArgument(sort != null);
		return repository.findAll(sort);
	}

	public Page<T> findAll(Pageable pageable) {
		checkArgument(pageable != null);
		return repository.findAll(pageable);
	}

	public T saveAndFlush(T entity) {
		return repository.saveAndFlush(entity);
	}

	public void flush() {
		repository.flush();
	}

	public List<T> findAll(int page, int size) {
		checkState(size <= 50 && size > 0 && page >= 0);
		return repository.findAll(new PageRequest(page, size)).getContent();
	}

	public R getRepository() {
		return repository;
	}
}
